package cn.tedu.csmall.stock.webapi.controller;

import cn.tedu.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import cn.tedu.csmall.commons.restful.JsonResult;
import cn.tedu.csmall.commons.restful.ResponseCode;
import cn.tedu.csmall.stock.service.IStockService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/base/stock")
@Api(tags = "库存管理模块")
public class StockController {

    @Autowired
    private IStockService stockService;

    @GetMapping("/reduce/count")
    @ApiOperation("减少库存数的方法")
    // @SentinelResource添加在控制层的方法上,在这个方法运行一次后
    // 会被Sentinel仪表台识别,识别后可以设置这个方法的限流策略
    // 如果方法不运行,仪表台中不会有这个方法
    // "减少库存数",是仪表台识别这个方法时显示的名称
    // blockHandler是注解中的属性,它指定当方法被限流时,运行的自定义限流方法名称
    // fallback是注解中的属性,它可以指定当前控制器方法运行发生异常时,运行指定的方法,
    //          优先级比统一异常处理类高
    @SentinelResource(  value = "减少库存数",
                        blockHandler = "blockError",
                        fallback = "fallbackError")
    public JsonResult reduceCount(StockReduceCountDTO stockReduceCountDTO){
        // 调用减少库存数的业务逻辑层方法,如果发生异常,会由全局异常处理类处理
        stockService.reduceStockCount(stockReduceCountDTO);

        return JsonResult.ok("库存减少完成!");
    }

    // Sentinel自定义限流方法规则
    // 1.访问修饰符必须是public
    // 2.返回值类型必须和被限流的控制器方法一致
    // 3.方法名必须和@SentinelResource注解中设置的名称一致
    // 4.参数列表必须和控制器方法一致,再添加一个BlockException类型参数在参数列表末尾
    public JsonResult blockError(StockReduceCountDTO stockReduceCountDTO,
                                 BlockException e){
        // 这个方法会在请求被限流时运行,一般用于给出相应提示
        return JsonResult.failed(
                ResponseCode.INTERNAL_SERVER_ERROR,"服务器忙,请稍后再试");
    }

    // 自定义降级方法定义规则和限流方法基本一致
    // 参数列表末尾添加的异常类型是Throwable
    // 当目标控制器方法发生异常时,会运行这个方法,异常对象会被throwable接收
    // 实际开发中可以运行之前较老的版本,所以叫"降级"
    public JsonResult fallbackError(StockReduceCountDTO stockReduceCountDTO,
                                    Throwable throwable){
        // 输出异常信息到控制台
        throwable.printStackTrace();
        // 返回降级方法运行的提示
        return JsonResult.failed(
                ResponseCode.INTERNAL_SERVER_ERROR,"方法异常,服务降级");
    }

}









